from django.db import models
from django.core.validators import MinValueValidator, MaxValueValidator
from django.utils import timezone


class KnowledgeMasteryProfile(models.Model):
    """
    用户知识点掌握度画像 - 核心模型
    基于现有score.KnowledgePoint和ExamRecord构建
    """
    student = models.ForeignKey(
        'users.Student',
        on_delete=models.CASCADE,
        related_name="knowledge_profiles",
        verbose_name="关联学生"
    )
    knowledge_point = models.ForeignKey(
        'score.KnowledgePoint',
        on_delete=models.CASCADE,
        related_name="mastery_profiles",
        verbose_name="关联知识点"
    )

    # 掌握度指标
    mastery_level = models.FloatField(
        default=0.0,
        validators=[MinValueValidator(0.0), MaxValueValidator(1.0)],
        verbose_name="掌握度",
        help_text="0-1之间的掌握度分数"
    )
    confidence = models.FloatField(
        default=0.0,
        validators=[MinValueValidator(0.0), MaxValueValidator(1.0)],
        verbose_name="置信度",
        help_text="数据量的置信程度"
    )

    # 练习统计
    total_practices = models.IntegerField(
        default=0,
        verbose_name="总练习次数"
    )
    correct_practices = models.IntegerField(
        default=0,
        verbose_name="正确次数"
    )
    total_exposure = models.IntegerField(
        default=0,
        verbose_name="总出现次数",
        help_text="在考试/练习中出现的总次数"
    )

    # 时间相关
    first_encountered = models.DateTimeField(
        null=True,
        blank=True,
        verbose_name="首次遇到时间"
    )
    last_practiced = models.DateTimeField(
        null=True,
        blank=True,
        verbose_name="最后练习时间"
    )
    mastery_trend = models.CharField(
        max_length=10,
        choices=[
            ('improving', '📈 提升中'),
            ('stable', '➡️ 稳定'),
            ('declining', '📉 下降'),
            ('volatile', '🔀 波动'),
        ],
        default='stable',
        verbose_name="掌握趋势"
    )

    # 难度感知
    perceived_difficulty = models.FloatField(
        default=0.5,
        validators=[MinValueValidator(0.0), MaxValueValidator(1.0)],
        verbose_name="感知难度",
        help_text="用户主观感受的难度"
    )
    actual_difficulty = models.FloatField(
        default=0.5,
        validators=[MinValueValidator(0.0), MaxValueValidator(1.0)],
        verbose_name="实际难度",
        help_text="基于正确率计算的客观难度"
    )

    # 学习状态
    LEARNING_STATUS_CHOICES = [
        ('not_started', '🆕 未开始'),
        ('learning', '📖 学习中'),
        ('reviewing', '🔄 复习中'),
        ('mastered', '✅ 已掌握'),
        ('struggling', '⚠️ 困难中'),
    ]
    learning_status = models.CharField(
        max_length=20,
        choices=LEARNING_STATUS_CHOICES,
        default='not_started',
        verbose_name="学习状态"
    )

    # 复习建议
    next_review_date = models.DateField(
        null=True,
        blank=True,
        verbose_name="建议复习日期"
    )
    study_priority = models.IntegerField(
        default=3,
        validators=[MinValueValidator(1), MaxValueValidator(5)],
        verbose_name="学习优先级",
        help_text="1-5，数字越大优先级越高"
    )

    # 系统字段
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        verbose_name = "知识点掌握度画像"
        verbose_name_plural = "知识点掌握度画像"
        unique_together = ['student', 'knowledge_point']
        indexes = [
            models.Index(fields=['student', 'mastery_level']),
            models.Index(fields=['student', 'study_priority', 'mastery_level']),
            models.Index(fields=['next_review_date']),
        ]
        ordering = ['student', '-study_priority', 'mastery_level']

    def __str__(self):
        return f"{self.student.name} - {self.knowledge_point.name}: {self.mastery_level:.2f}"

    @property
    def accuracy_rate(self):
        """计算正确率"""
        if self.total_practices == 0:
            return 0.0
        return self.correct_practices / self.total_practices

    @property
    def exposure_rate(self):
        """计算出现率（知识点覆盖率）"""
        if self.total_exposure == 0:
            return 0.0
        return self.total_practices / self.total_exposure

    @property
    def needs_review(self):
        """是否需要复习"""
        if not self.next_review_date:
            return False
        return timezone.now().date() >= self.next_review_date

    @property
    def improvement_potential(self):
        """提升潜力：低掌握度 + 高权重 = 高潜力"""
        return (1 - self.mastery_level) * self.knowledge_point.weight


class KnowledgePracticeRecord(models.Model):
    """
    知识点练习记录 - 关联现有考试记录和失分记录
    """
    student = models.ForeignKey(
        'users.Student',
        on_delete=models.CASCADE,
        related_name="knowledge_practices",
        verbose_name="关联学生"
    )
    knowledge_point = models.ForeignKey(
        'score.KnowledgePoint',
        on_delete=models.CASCADE,
        related_name="practice_records",
        verbose_name="关联知识点"
    )

    # 关联到现有的考试记录和失分记录
    exam_record = models.ForeignKey(
        'score.ExamRecord',
        on_delete=models.CASCADE,
        null=True,
        blank=True,
        related_name="knowledge_practices",
        verbose_name="关联考试记录"
    )
    score_loss_detail = models.ForeignKey(
        'score.ScoreLossDetail',
        on_delete=models.CASCADE,
        null=True,
        blank=True,
        related_name="knowledge_practices",
        verbose_name="关联失分记录"
    )

    # 练习结果
    PRACTICE_RESULT_CHOICES = [
        ('correct', '✅ 正确'),
        ('incorrect', '❌ 错误'),
        ('partial', '⚠️ 部分正确'),
        ('unattempted', '⏸️ 未尝试'),
    ]
    result = models.CharField(
        max_length=15,
        choices=PRACTICE_RESULT_CHOICES,
        verbose_name="练习结果"
    )
    score_impact = models.FloatField(
        default=0.0,
        verbose_name="分数影响",
        help_text="正数为得分，负数为失分"
    )
    time_spent = models.IntegerField(
        null=True,
        blank=True,
        verbose_name="用时(秒)",
        help_text="解答该知识点题目花费的时间"
    )

    # 难度和复杂度
    question_difficulty = models.FloatField(
        default=0.5,
        validators=[MinValueValidator(0.0), MaxValueValidator(1.0)],
        verbose_name="题目难度"
    )
    complexity_level = models.IntegerField(
        default=1,
        validators=[MinValueValidator(1), MaxValueValidator(3)],
        verbose_name="复杂度等级",
        help_text="1-基础, 2-中等, 3-综合"
    )

    # 用户反馈
    user_confidence = models.FloatField(
        null=True,
        blank=True,
        validators=[MinValueValidator(0.0), MaxValueValidator(1.0)],
        verbose_name="答题信心",
        help_text="用户答题时的自信程度"
    )
    notes = models.TextField(
        blank=True,
        verbose_name="笔记",
        help_text="解题思路、错误原因等"
    )

    # 时间戳
    practiced_at = models.DateTimeField(
        default=timezone.now,
        verbose_name="练习时间"
    )
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        verbose_name = "知识点练习记录"
        verbose_name_plural = "知识点练习记录"
        indexes = [
            models.Index(fields=['student', 'knowledge_point', 'practiced_at']),
            models.Index(fields=['practiced_at']),
        ]
        ordering = ['-practiced_at']

    def __str__(self):
        return f"{self.student.name} - {self.knowledge_point.name} - {self.get_result_display()}"


"""
主要的作用是各个知识点之间的各种关系，不能仅仅是父子关系，而也可能是关联，前置等等关系
"""
class KnowledgeRelationship(models.Model):
    """
    知识点关联关系 - 扩展现有的知识点树形结构
    """
    source_knowledge = models.ForeignKey(
        'score.KnowledgePoint',
        on_delete=models.CASCADE,
        related_name="outgoing_relationships",
        verbose_name="源知识点"
    )
    target_knowledge = models.ForeignKey(
        'score.KnowledgePoint',
        on_delete=models.CASCADE,
        related_name="incoming_relationships",
        verbose_name="目标知识点"
    )

    # 关系类型
    RELATIONSHIP_TYPES = [
        ('prerequisite', '📚 前置知识'),
        ('related', '🔄 关联知识'),
        ('enhanced_by', '⬆️ 强化知识'),
        ('confused_with', '⚠️ 易混淆'),
        ('alternative', '🔄 替代解法'),
    ]
    relationship_type = models.CharField(
        max_length=20,
        choices=RELATIONSHIP_TYPES,
        verbose_name="关系类型"
    )

    # 关系强度
    strength = models.FloatField(
        default=0.5,
        validators=[MinValueValidator(0.0), MaxValueValidator(1.0)],
        verbose_name="关系强度"
    )
    confidence = models.FloatField(
        default=0.5,
        validators=[MinValueValidator(0.0), MaxValueValidator(1.0)],
        verbose_name="置信度"
    )

    # 应用场景
    application_context = models.TextField(
        blank=True,
        verbose_name="应用场景",
        help_text="这种关系在什么情况下重要"
    )

    # 系统字段
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        verbose_name = "知识点关联"
        verbose_name_plural = "知识点关联关系"
        unique_together = ['source_knowledge', 'target_knowledge', 'relationship_type']
        indexes = [
            models.Index(fields=['source_knowledge', 'relationship_type']),
        ]

    def __str__(self):
        return f"{self.source_knowledge.name} → {self.get_relationship_type_display()} → {self.target_knowledge.name}"


class StudyRecommendation(models.Model):
    """
    学习推荐 - 基于知识点掌握度的个性化推荐
    """
    student = models.ForeignKey(
        'users.Student',
        on_delete=models.CASCADE,
        related_name="study_recommendations",
        verbose_name="关联学生"
    )
    knowledge_point = models.ForeignKey(
        'score.KnowledgePoint',
        on_delete=models.CASCADE,
        related_name="study_recommendations",
        verbose_name="推荐知识点"
    )

    # 推荐理由
    RECOMMENDATION_TYPES = [
        ('weak_point', '🎯 薄弱环节'),
        ('prerequisite', '📚 前置知识'),
        ('high_yield', '💎 高分值知识点'),
        ('trending', '📈 提升趋势好'),
        ('quick_win', '⚡ 快速提分'),
        ('exam_focus', '🏆 考试重点'),
    ]
    recommendation_type = models.CharField(
        max_length=20,
        choices=RECOMMENDATION_TYPES,
        verbose_name="推荐类型"
    )

    # 推荐强度
    priority_score = models.FloatField(
        default=0.0,
        validators=[MinValueValidator(0.0), MaxValueValidator(1.0)],
        verbose_name="优先级分数"
    )
    expected_improvement = models.FloatField(
        default=0.0,
        verbose_name="预期提分",
        help_text="掌握该知识点后预期能提升的分数"
    )
    time_estimate = models.IntegerField(
        verbose_name="预计用时(分钟)",
        help_text="预计需要的学习时间"
    )

    # 推荐内容
    study_strategy = models.TextField(
        verbose_name="学习策略",
        help_text="具体的学习方法和建议"
    )
    recommended_resources = models.TextField(
        blank=True,
        verbose_name="推荐资源",
        help_text="推荐的学习资料和练习题"
    )
    practice_focus = models.TextField(
        blank=True,
        verbose_name="练习重点",
        help_text="需要重点练习的题型和方法"
    )

    # 状态跟踪
    is_accepted = models.BooleanField(
        default=False,
        verbose_name="是否接受"
    )
    is_completed = models.BooleanField(
        default=False,
        verbose_name="是否完成"
    )
    completed_at = models.DateTimeField(
        null=True,
        blank=True,
        verbose_name="完成时间"
    )

    # 反馈
    student_feedback = models.TextField(
        blank=True,
        verbose_name="学生反馈",
        help_text="学生对推荐内容的反馈"
    )
    effectiveness_rating = models.IntegerField(
        null=True,
        blank=True,
        validators=[MinValueValidator(1), MaxValueValidator(5)],
        verbose_name="效果评分",
        help_text="1-5分，学生对推荐效果的评分"
    )

    # 时间字段
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    expires_at = models.DateTimeField(
        null=True,
        blank=True,
        verbose_name="过期时间",
        help_text="推荐的过期时间"
    )

    class Meta:
        verbose_name = "学习推荐"
        verbose_name_plural = "学习推荐"
        indexes = [
            models.Index(fields=['student', 'priority_score']),
            models.Index(fields=['student', 'is_completed', 'is_accepted']),
        ]
        ordering = ['student', '-priority_score', 'created_at']

    def __str__(self):
        return f"{self.student.name} - {self.knowledge_point.name} ({self.get_recommendation_type_display()})"

    @property
    def is_active(self):
        """推荐是否活跃"""
        if self.expires_at and timezone.now() > self.expires_at:
            return False
        return not self.is_completed

    @property
    def efficiency_score(self):
        """学习效率分数：预期提分 / 预计用时"""
        if self.time_estimate == 0:
            return 0.0
        return self.expected_improvement / self.time_estimate